﻿using System;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MissingLinq.Linq2Management.Context;
using MissingLinq.Linq2Management.Model.CIMv2;

namespace MissingLinq.Linq2Management.Test.Context
{
	[TestClass]
	public class QueryTranslatorWhereUnitTest
	{
		[TestMethod]
		public void BinaryConstantWhereWithString()
		{
			var translator = new QueryTranslator("Win32_Share");

			String query = translator.Translate(Where<Win32Share>(s => s.Name != "Test"));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (Name <> 'Test')");

			query = translator.Translate(Where<Win32Share>(s => s.Name == "Test"));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (Name = 'Test')");
		}

		[TestMethod]
		public void BinaryConstantWhereWithNumeric()
		{
			var translator = new QueryTranslator("Win32_Process");

			String query = translator.Translate(Where<Win32Process>(p => p.ProcessId == 1));
			Assert.AreEqual(query, "SELECT * FROM Win32_Process WHERE (ProcessId = 1)");

			query = translator.Translate(Where<Win32Process>(p => p.ProcessId != 1));
			Assert.AreEqual(query, "SELECT * FROM Win32_Process WHERE (ProcessId <> 1)");

			query = translator.Translate(Where<Win32Process>(p => p.ProcessId > 1));
			Assert.AreEqual(query, "SELECT * FROM Win32_Process WHERE (ProcessId > 1)");

			query = translator.Translate(Where<Win32Process>(p => p.ProcessId < 1));
			Assert.AreEqual(query, "SELECT * FROM Win32_Process WHERE (ProcessId < 1)");

			query = translator.Translate(Where<Win32Process>(p => p.ProcessId >= 1));
			Assert.AreEqual(query, "SELECT * FROM Win32_Process WHERE (ProcessId >= 1)");

			query = translator.Translate(Where<Win32Process>(p => p.ProcessId <= 1));
			Assert.AreEqual(query, "SELECT * FROM Win32_Process WHERE (ProcessId <= 1)");
		}

		[TestMethod]
		public void BinaryConstantWhereWithEnum()
		{
			var translator = new QueryTranslator("Win32_Share");

			String query = translator.Translate(Where<Win32Share>(s => s.Type == Win32ShareType.DiskDrive));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (Type = 0)");

			query = translator.Translate(Where<Win32Share>(s => s.Type != Win32ShareType.DiskDrive));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (Type <> 0)");

			query = translator.Translate(Where<Win32Share>(s => s.Type > Win32ShareType.DiskDrive));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (Type > 0)");

			query = translator.Translate(Where<Win32Share>(s => s.Type < Win32ShareType.DiskDrive));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (Type < 0)");

			query = translator.Translate(Where<Win32Share>(s => s.Type >= Win32ShareType.DiskDrive));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (Type >= 0)");

			query = translator.Translate(Where<Win32Share>(s => s.Type <= Win32ShareType.DiskDrive));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (Type <= 0)");
		}

		[TestMethod]
		public void BinaryConstantWhereWithAndOrAlso()
		{
			var translator = new QueryTranslator("Win32_Share");

			String query = translator.Translate(Where<Win32Share>(s => s.Name != "Test" && s.Name != "Test2"));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE ((Name <> 'Test') AND (Name <> 'Test2'))");

			query = translator.Translate(Where<Win32Share>(s => s.Name == "Test" || s.Name == "Test2"));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE ((Name = 'Test') OR (Name = 'Test2'))");

			query = translator.Translate(Where<Win32Share>(s => s.Name != "Test" && s.Name != "Test2" && s.Name != "Test3"));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (((Name <> 'Test') AND (Name <> 'Test2')) AND (Name <> 'Test3'))");

			query = translator.Translate(Where<Win32Share>(s => s.Name == "Test" || s.Name == "Test2" || s.Name == "Test3"));
			Assert.AreEqual(query, "SELECT * FROM Win32_Share WHERE (((Name = 'Test') OR (Name = 'Test2')) OR (Name = 'Test3'))");
		}

		[TestMethod]
		public void Test()
		{
			var dc = new ManagementObjectContext();
			var shares = dc.CIMv2.Win32Shares.ToArray();
			foreach(var share in shares)
				System.Diagnostics.Debug.WriteLine(share.ToString());
		}

		private Expression Where<TSource>(Expression<Func<TSource, Boolean>> expression)
		{
			return (new MockQueryable<TSource>().Where(expression)).Expression;
		}
	}
}
